package com.ruoyi.yz.service.impl;

import com.ruoyi.face.domain.Member;
import com.ruoyi.face.domain.QueryCondition;
import com.ruoyi.face.domain.QueryResult;
import com.ruoyi.face.domain.SubScribe;
import com.ruoyi.face.service.FaceDevice;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.yz.domain.YzMember;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class FaceDeviceService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private FaceDevice faceDevice;

    private Lock lock = new ReentrantLock();

    private ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();

    @PostConstruct
    private void init() {
        updateDeviceHost();

        faceDevice.doLogin();

        scheduledExecutor.scheduleWithFixedDelay(() -> {
            if (!faceDevice.isLogin()) {
                return;
            }
            // for heart beat
            ResponseEntity<String> response = null;
            try {
                faceDevice.status();
            } catch (Exception e) {
                logger.warn("heart beat err: {}", e.getMessage());
                if (e instanceof HttpClientErrorException.Unauthorized) {
                    faceDevice.doLogin();
                }
            }
            logger.trace("heart beat: {}", response.getBody());
        }, 60,60, TimeUnit.SECONDS);
    }

    @PreDestroy
    private void destroy() {
        scheduledExecutor.shutdown();
        try {
            scheduledExecutor.awaitTermination(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            scheduledExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    private void updateDeviceHost() {
        String host = configService.selectConfigByKey("device.face.webapi");
        faceDevice.updateDeviceHost(host);
    }

    public void updateDeviceConfig() {
        updateDeviceHost();
        if (!faceDevice.isLogin()) {
            faceDevice.doLogin();
        }
        SubScribe data = new SubScribe();
        data.setServerUri(configService.selectConfigByKey("device.face.push"));
        faceDevice.setSubscribePush(data);
        logger.info("device set push url: {}", data.getServerUri());
    }

    public boolean isLogin() {
        return faceDevice.isLogin();
    }

    public QueryResult<Member> queryMember(QueryCondition query) {
        return faceDevice.queryMember(query);
    }

    public boolean deleteMemberByIds(List<Long> ids) {
        return faceDevice.deleteMemberByIds(ids);
    }


    public void updateMemberById(Member deviceMember) {
        faceDevice.updateMemberById(deviceMember);
    }

    @Async
    public void syncAll(List<YzMember> members) {
        if (lock.tryLock()) {
            try {
                members.forEach(yzMember -> {
                    try {
                        Member member = faceDevice.getMemberById(yzMember.getId());
                        updateMemberById(yzMember.createDeviceMember());
                    } catch (HttpClientErrorException.NotFound e) {
                        try {
                            faceDevice.addMember(yzMember.createDeviceMember());
                        } catch (Exception err) {
                            logger.warn("sync all add member error: id={} - {}", yzMember.getId(), err.getMessage());
                        }
                    } catch (Exception e) {
                        logger.warn("sync all error: id={} - {}", yzMember.getId(), e.getMessage());
                    }
                });
            } catch (Exception e) {
                logger.warn("sync all exception: {}", e.getMessage());
            } finally {
                lock.unlock();
            }
        }
    }

    public void doLogin() {
        faceDevice.doLogin();
    }
}
